using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MvcCms.Core.Cache;
using MvcCms.Data;

using Raccoom.Xml;
using System.Collections.Specialized;
using MvcCms.Service.Code.Membership;
using MvcCms.Service.Code;

namespace MvcCms.Service.Cache
{
    public class CacheService : ICacheService
    {
        private const string CategoriesHolder = "Categories";
        private const string LanguagesHolder = "Languages";
        private const string PortalsHolder = "Portals";
        private const string StatesHolder = "States";
        private const string SubPagesHolder = "SubPages";
        private const string MembershipConfigHolder = "MembershipConfig";

        private const string WeightedContentWidgetsHolder = "WeightedContentWidgets";
        private const string WeightedContentModulesHolder = "WeightedContentModules";

        #region Constructors

        private readonly Core.Cache.ICacheService _coreService;
        private readonly IInMemoryCache _inmemorycacheService;
        private readonly IMiscRepository _miscRepository;
        private readonly IPortalRepository _portalRepository;
        private readonly ICmsRepository _cmsRepository;
        public CacheService(ICmsRepository cmsRepository, IPortalRepository portalRepository, IInMemoryCache inmemorycacheService,
                             IMiscRepository miscRepository, Core.Cache.ICacheService coreService)
        {
            _cmsRepository = cmsRepository;
            _portalRepository = portalRepository;
            _inmemorycacheService = inmemorycacheService;
            _miscRepository = miscRepository;
            _coreService = coreService;
        }

        #endregion

        #region Cms Methods
        public NameValueCollection GetMembershipConfig()
        {
            return _inmemorycacheService.Get(MembershipConfigHolder, () => CacheConfig.SetMemberShipConfig());
        }

        public IEnumerable<WeightedContentModule> ListWeightedContentModules()
        {
            return _inmemorycacheService.Get(WeightedContentModulesHolder, () => _cmsRepository.ListWeightedContentModulesForCache());
        }

        public IEnumerable<WeightedContentWidget> ListWeightedContentWidgets()
        {
            return _inmemorycacheService.Get(WeightedContentWidgetsHolder, () => _cmsRepository.ListWeightedContentWidgetsForCache());
        }

        public ContentPage GetPublishedCategoryContentPage(int routeCatId)
        {
            return _coreService.GetPublishedCategoryContentPage(routeCatId);
        }

        public ContentCategory GetCorrectCategory(int routeCatId, string routePath)
        {
            return _coreService.GetCorrectCategory(routeCatId, routePath);
        }

        public ContentCategory GetCurrentCategory()
        {
            return _coreService.GetCurrentCategory();
        }

        public ContentPage GetContentSubPageByPath(string path, int routeCatId)
        {
            return _coreService.GetContentSubPageByPath(path, routeCatId);
        }

        public ContentPage GetPublishedSubCategoryContentPage(string path)
        {
            return _coreService.GetPublishedSubCategoryContentPage(path);
        }

        public IEnumerable<ContentCategory> ListTopNav()
        {
            return _coreService.ListTopNav();
        }

        public IList<ContentCategory> ListCategoriesHierarchy()
        {
            return _coreService.ListCategoriesHierarchy();
        }

        public IEnumerable<ContentPage> ListSubPages(int catId)
        {
            return _coreService.ListSubPages(catId);
        }

        public IEnumerable<ContentPage> ListAltLanguagePages(int parentPageId)
        {
            return _coreService.ListAltLanguagePages(parentPageId);
        }
        #endregion

        #region ICacheService Members

        public RssChannel GetRssFeed(string feedurl)
        {
            var uri = new Uri(feedurl);
            return _inmemorycacheService.Get(feedurl, () => new RssChannel(uri));
        }

        public Portal GetCurrentPortal()
        {
            //if httpcontext is null this is a unit test so just pick the default portal
            if (HttpContext.Current == null)
            {
                IEnumerable<Portal> portals = _inmemorycacheService.Get(PortalsHolder, () => _portalRepository.ListPortals());
                return portals.Where(portal => portal.Name.Equals("Default")).FirstOrDefault();
            }
            else
            {
                string url = "";

                //special code for integrated pipeline mode and azure, the request object won't be available in application_start
                var b = HttpContext.Current.GetType().GetField("HideRequestResponse", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                b.SetValue(HttpContext.Current, false);

                url = HttpContext.Current.Request.Url.Authority.ToLower();
                if (url != "127.0.0.1")
                {
                    if (!DevCheck.IsDev())
                    {
                        url = HttpContext.Current.Request.Url.Host.ToLower();
                    }
                    else
                    {
                        url = HttpContext.Current.Request.Url.Authority.ToLower();
                    }
                }
                else
                {
                    //on app start happens here
                    IEnumerable<Portal> portalsAppStart = _inmemorycacheService.Get(PortalsHolder, () => _portalRepository.ListPortals());
                    return portalsAppStart.Where(portal => portal.Name.Equals("Default")).FirstOrDefault();
                }

                IEnumerable<Portal> portals = _inmemorycacheService.Get(PortalsHolder, () => _portalRepository.ListPortals());
                try
                {
                    return portals.Where(portal => portal.URLAuthority.Equals(url)).FirstOrDefault();
                }
                catch
                {
                    //Call the core service where the connection can be reopened.
                    return _coreService.GetCurrentPortal();
                }
            }

        }

        public Language GetLanguage(int langId)
        {
            IEnumerable<Language> languages = _inmemorycacheService.Get(LanguagesHolder,
                                                                        () => _miscRepository.ListLanguages());
            return languages.Where(language => language.LanguageID.Equals(langId)).FirstOrDefault();
        }

        public StateProvince GetStateProvince(int stateId)
        {
            IEnumerable<StateProvince> states = _inmemorycacheService.Get(StatesHolder,
                                                                          () => _miscRepository.ListStates());
            return states.Where(state => state.StateProvinceID.Equals(stateId)).FirstOrDefault();
        }

        public StateProvince GetStateProvince(string abbreviation)
        {
            IEnumerable<StateProvince> states = _inmemorycacheService.Get(StatesHolder,
                                                                          () => _miscRepository.ListStates());
            return states.Where(state => state.StateProvinceCode.Trim().Equals(abbreviation)).FirstOrDefault();
        }

        public IEnumerable<Language> ListLanguages()
        {
            return _inmemorycacheService.Get(LanguagesHolder, () => _miscRepository.ListLanguages());
        }

        public IEnumerable<StateProvince> ListStates()
        {
            return _inmemorycacheService.Get(StatesHolder, () => _miscRepository.ListStates());
        }

        public void ClearPortals()
        {
            _inmemorycacheService.Remove(PortalsHolder);
        }

        public void ClearCategories()
        {
            _inmemorycacheService.Remove(CategoriesHolder);
            _inmemorycacheService.Remove(SubPagesHolder);
        }

        public void ClearLanguages()
        {
            _inmemorycacheService.Remove(LanguagesHolder);
        }

        #endregion
    }
}